<?php
declare (strict_types=1);

namespace app\admin\controller;

use app\common\tool\Result;
use think\facade\View;
use think\Response;

class Backup
{
    protected string $mysqldump_bin = 'mysqldump';
    protected string $mysql_bin = 'mysql';
    protected string $name = '备份';
    protected string $table = 'backup';

    public function getMysqlBin($bin): string
    {
        $password = env('DB_PASS') ? ' -p' . env('DB_PASS') : '';

        return env('MYSQL_PATH') . $bin . ' -h ' . env('DB_HOST') . ' -P ' . env('DB_PORT') . ' -u ' . env('DB_USER') . ' ' . $password . ' ' . env('DB_NAME');
    }

    public function index(): string
    {
        //需要过滤的文件
        $files = array_slice(scandir('backups', 1), 0, -3);
        $list = [];
        if (is_array($files)) {
            foreach ($files as $k => $v) {
                $filesize = filesize('backups/' . $v);
                if ($filesize < 1024) {
                    $size = sprintf("%01.2f", $filesize) . "B";
                } elseif ($filesize < 1024 * 1024) {
                    $size = sprintf("%01.2f", ($filesize / 1024)) . "KB";
                } elseif ($filesize < 1024 * 1024 * 1024) {
                    $size = sprintf("%01.2f", ($filesize / (1024 * 1024))) . "MB";
                } elseif ($filesize < 1024 * 1024 * 1024 * 1024) {
                    $size = sprintf("%01.2f", ($filesize / (1024 * 1024 * 1024))) . "GB";
                }
                $is_del = strstr($v, 'auto') == false ? 1 : 0;
                $list[] = [
                    'file'        => $v,
                    'size'        => $size,
                    'create_time' => filemtime('backups/' . $v),
                    'is_del'      => $is_del,
                ];
            }
        }
        View::assign('list', $list);
        View::assign('definePath', '{/}/static/admin/addons/builder/define/');

        return View::fetch();
    }

    public function add($auto = 0): array
    {
        try {
            $path = "backups/";//备份存放路径
            if ($auto == 1) {
                $name = env('DB_NAME') . "_auto_" . date("YmdHis") . ".sql";//备份名称
            } else {
                $name = env('DB_NAME') . "_" . date("YmdHis") . ".sql";//备份名称
            }
            $filePath = $path . $name;
            // 备份命令组合
            $exec = $this->getMysqlBin($this->mysqldump_bin) . ' > ' . $filePath;
            set_time_limit(0);
            exec($exec, $output, $res);
            if ($res != '0') {
                return ['code' => -1, 'msg' => '备份失败1'];
            } else {
                return ['code' => 1, 'msg' => '备份成功'];
            }

        } catch (\Exception $e) {

            return ['code' => -1, 'msg' => $e->getMessage()];
        }
    }

    public function ossAdd(): array
    {
        try {
            $path = "backups/";
            $name = env('DB_NAME') . "_OssBackup_" . date("Y-m-d_H-i-s") . ".sql";
            $filePath = $path . $name;
            $exec = $this->getMysqlBin($this->mysqldump_bin) . ' > ' . $filePath;
            set_time_limit(0);
            exec($exec, $output, $res);
            if ($res != '0') {
                return ['code' => 0, 'msg' => '备份失败1'];
            } else {
                return ['code' => 1, 'msg' => '备份成功', 'name' => $name, 'path' => $filePath];
            }

        } catch (\Exception $e) {

            return ['code' => 1, 'msg' => $e->getMessage()];
        }
    }

    public function import($file): Response
    {
        $sql_file = "backups/" . $file;
        if (!file_exists($sql_file)) return Result::fail('文件不存在，请检查');

        //还原备份前先做一个备份
        $add_res = $this->add();
        if ($add_res['code'] != 1) return Result::fail('数据备份失败');

        //还原备份
        $exec = $this->getMysqlBin($this->mysql_bin) . ' < ' . $sql_file;
        set_time_limit(0);
        exec($exec, $output, $res);
        if ($res != '0') {
            return Result::fail('备份还原失败');
        } else {
            return Result::success('备份还原成功');
        }
    }

    public function delete(array $file): bool
    {
        foreach ($file as $v) {
            unlink('backups/' . $v);
        }

        return true;
    }

    public function clear(): Response
    {
        //清空前先备份数据
        $add_res = $this->add();
        if ($add_res['code'] != 1) return Result::fail('数据备份失败');
        $sql_file = app()->getAppPath() . '/clear/clear.sql';
        //还原备份
        $exec = $this->getMysqlBin($this->mysql_bin) . ' < ' . $sql_file;
        set_time_limit(0);
        exec($exec, $output, $res);
        if ($res != '0') {
            return Result::fail('清空失败');
        } else {
            return Result::success('已清空');
        }
    }
}